home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Archive / Graphics / QuickDraw GX / GX->PostScript Sample / GXToPostScript / Imaging Engine / BitmapPrimitives.c next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  39.5 KB  |  1,315 lines  |  [TEXT/MPS ]

  1. /*
  2.      File:        BitmapPrimitives.c
  3.  
  4.      Contains:    QuickDraw GX to PostScript conversion code.
  5.                          File contains routines to translate Bitmap shapes 
  6.                         into PostScript.
  7.  
  8.      Version:    Technology:    Quickdraw GX 1.1.x
  9.       
  10.      Copyright:    © 1991-1997 by Apple Computer, Inc., all rights reserved.
  11. */
  12.  
  13. #include "GXToPSBuildConfig.h"
  14. #include <GXGraphics.h>
  15. #include "GXGraphicsPriv.h"
  16. #include <GXEnvironment.h>
  17. #include "GXToPostScript.h"
  18. #include "IOUtilities.h"
  19. #include "RDUtil.h"
  20. #include "FontHandler.h"
  21. #include "PublicPostScriptIE.h"
  22. #include "private.h"
  23. #include "PSIEResources.h"
  24. #include "GXErrors.h"
  25. #include <OffscreenLibrary.h>
  26. #include "ShapeUtilities.h"
  27. #include <String.h>
  28. #include <Memory.h>
  29.  
  30. #ifdef resumeLabel
  31.     #undef resumeLabel
  32. #endif
  33. #define resumeLabel(exception)
  34.  
  35. /*********************************************
  36.  
  37.     Function:    CountPSDeviceSpaceComponents:
  38.     
  39.     Function returns the number of color components in a color space.
  40.     Will return zero for illegal PostScript device spaces.
  41.     
  42. **********************************************/
  43. long CountPSDeviceSpaceComponents(gxColorSpace theSpace);
  44. long CountPSDeviceSpaceComponents(gxColorSpace theSpace)
  45.     {
  46.         long            nComponents;
  47.         
  48.         switch (theSpace) {
  49.         
  50.             case gxRGBSpace:
  51.                 nComponents = 3;
  52.                 break;
  53.                 
  54.             case gxGraySpace:
  55.                 nComponents = 1;
  56.                 break;
  57.                 
  58.             case gxCMYKSpace:
  59.                 nComponents = 4;
  60.                 break;
  61.             
  62.             default:
  63.                 nComponents = 0;            // Has to be one of the other three.
  64.                 break;
  65.         
  66.         }//end switch
  67.  
  68.         return(nComponents);
  69.         
  70.     }//CountPSDeviceSpaceComponents
  71.  
  72. //<FF>
  73. /************************************************
  74.  
  75.     Routine: MatchColorSetValues
  76.     
  77.     Routine matches an array of set colors in place:
  78.     
  79.         nColors:                # of colors in array
  80.         theSetColors:        Array of set colors.
  81.         setSpace:                Color space of color set.
  82.         setProfile:            Color profile of color set.
  83.         spaceToUse:            Color space to convert to.
  84.         profileToUse:        Color profile to convert to.
  85. ************************************************/
  86. void MatchColorSetValues(long nColors, gxSetColor *theSetColors, gxColorSpace setSpace, gxColorProfile setProfile, gxColorSpace spaceToUse, gxColorProfile profileToUse);
  87. void MatchColorSetValues(long nColors, gxSetColor *theSetColors,  gxColorSpace setSpace, gxColorProfile setProfile,  gxColorSpace spaceToUse, gxColorProfile profileToUse)
  88.     {
  89.         gxSetColor*            pSet;
  90.         long                        i;
  91.         gxColor                    tableEntry;
  92.     
  93.         pSet = theSetColors;
  94.         for (i = nColors - 1; i >= 0; --i) {
  95.             
  96.             tableEntry.space = setSpace;
  97.             tableEntry.profile = setProfile;
  98.             
  99.             // Move the component data into a color record for conversion.
  100.             memcpy(&(tableEntry.element.component[0]), pSet, 4 * sizeof(gxColorValue) );
  101.             
  102.             GXConvertColor(&tableEntry, spaceToUse, nil, profileToUse);
  103.             
  104.             // Move it back.
  105.             BlockMove((Ptr)&(tableEntry.element.component[0]), (Ptr)pSet, 4 * sizeof(gxColorValue));
  106.         
  107.             ++pSet;
  108.         
  109.         }//end for
  110.     
  111.     }//MatchColorSetValues
  112.  
  113.  
  114. //<FF>
  115. /************************************************
  116.  
  117.     Routine:        OutputComponentArrays:
  118.     
  119.     Routine outputs the component arrays for a color set
  120.     onto the postscript operand stack.
  121.     
  122.     pRDParams:            pointer to the RD parameter block.
  123.     nColors:                number of colors in the color set.
  124.     theSetColors:        Array of setColors 
  125.     nComponents:        Number of components in color space.
  126.     level2Color:        output for level2 color?
  127.     whatSpace:            what color space is this set?
  128.  
  129. ************************************************/
  130. OSErr OutputComponentArrays( TRDParams *pRDParams, long nColors, gxSetColor *theSetColors, long nComponents, Boolean level2Color, gxColorSpace whatSpace);
  131. OSErr OutputComponentArrays( TRDParams *pRDParams, long nColors, gxSetColor *theSetColors, long nComponents, Boolean level2Color, gxColorSpace whatSpace)
  132.     {
  133.         OSErr            status = noErr;
  134.         long            i, j;
  135.         Ptr                pComp;
  136.         
  137.         for (i = 0; i < nComponents; i++) {
  138.  
  139.             pRDParams->resIndex = kNewArray;                        // Create an array, leave it and 0 on operand stack.
  140.             status = RDResPrintf(pRDParams, nColors);        //    Array has one entry for each color.
  141.             nrequire(status, failed_Output);
  142.             
  143.             pComp =(Ptr)(&(theSetColors[0].component[i]));
  144.  
  145.             /** 
  146.                 Prior to 1.2 we used to do this: For level-2 colors, output the short, otherwise output it as a fixed,
  147.                         now we always output a fixed, but we need to handle XYZ in a special case because the normalization is different.
  148.             **/
  149.  
  150.             pRDParams->resIndex = kPutFixed;
  151.             
  152.             for (j = 0; j < nColors; j++) {
  153.                 
  154.                 if (whatSpace != gxXYZSpace)
  155.                     status = RDResPrintf(pRDParams, COMPONENTtoFIXED(*(unsigned short*)pComp)    );
  156.                 else
  157.                     status = RDResPrintf(pRDParams, XYZCOMPONENTtoFIXED(*(unsigned short*)pComp)    );
  158.                     
  159.                 nrequire(status, failed_Output);
  160.                 
  161.                 pComp += sizeof(gxSetColor);
  162.             
  163.             }//end for
  164.             
  165.             pRDParams->resIndex = kDoPop;
  166.             nrequire( status = RDResPrintf(pRDParams), failed_Output);        // pop last copy of index off stack.
  167.                     
  168.         }//end for
  169.  
  170. failed_Output:
  171.         return(status);    
  172.     
  173.     }//OutputComponentArrays
  174.  
  175. //<FF>
  176. /************************************************
  177.  
  178.     ColorSetPrimitive
  179.     
  180.     Routine creates an indexed color space dictionary
  181.     for the Graphics state.  The dictionary for the colorSet
  182.     dictionary is left on the operand stack.
  183.     
  184.     hIEGlobals:            Imaging Engine globals handle
  185.     theSet:                    The color set to output.
  186.     theProfile:            The color profile associated with whatever the colorSet was associated with
  187.                                         since colorSets have no meaning on their own.
  188.     
  189. **************************************************/
  190. OSErr ColorSetPrimitive(TIEGlobalsHdl hIEGlobals, gxColorSet theSet, gxColorProfile theProfile)
  191.     {
  192.         OSErr                        status;
  193.         TIEGlobalsPtr        pGlobals;
  194.         TRDParams*            pRDParams;            
  195.         gxColorSpace        spaceToUse;                    // Color space to use for printer
  196.         gxColorProfile    profileToUse;                // Profile to use for the printer
  197.         short                        nColors;                        // Number of colors 
  198.         gxColorSpace        setSpace;                        // Color space of the color set.
  199.         gxSetColor            *theSetColors;            // Array of set colors from the color set.
  200.         long                        nComponents;                // Number of components in the color space to use.
  201.         Boolean                    level2Color;                // Are we doing level-2 color?
  202.         Boolean                    useDeviceSpace;            // Are we doing printer device space (no matching)?
  203.         
  204.         pGlobals = *hIEGlobals;
  205.         pRDParams = pGlobals->pRDParams;
  206.  
  207.         
  208.         /*** Allocate temporary storage for the colors ***/
  209.         
  210.         nColors = GXGetColorSet(theSet, nil, nil);
  211.         require(nColors <= 256, failed_ColorSpace);
  212.         nrequire(status = GXGetGraphicsError(nil), failed_ColorSpace);
  213.  
  214.         status = PSSetWorkSpaceSize(hIEGlobals, nColors * sizeof(gxSetColor));
  215.         nrequire(status, failed_GetWrkSpace);
  216.         
  217.         HLockHi((*hIEGlobals)->hWorkSpace);
  218.         
  219.         theSetColors = (gxSetColor*)(*((*hIEGlobals)->hWorkSpace));
  220.     
  221.         /*** Get the colors ***/
  222.         
  223.         GXGetColorSet(theSet, &setSpace, theSetColors);
  224.         
  225.         /** Figure out how color space to translate to and how many components **/
  226.         
  227.         if ((*hIEGlobals)->params.renderOptions & gxUseLevel2ColorOption) {
  228.         
  229.             status = GetLevel2ColorSpace(setSpace, theProfile, &spaceToUse, &nComponents, &useDeviceSpace);
  230.             nrequire(status, failed_ColorSpace);
  231.             profileToUse = theProfile;
  232.             level2Color = true;
  233.             
  234.         } else {
  235.         
  236.             spaceToUse = (*hIEGlobals)->params.devCSpace;
  237.             profileToUse = pGlobals->params.devCProfile;
  238.             level2Color = false;
  239.             nComponents = CountPSDeviceSpaceComponents(spaceToUse);
  240.             require(nComponents, failed_InvalidShapeSpace);
  241.         
  242.         }//end if
  243.         
  244.         
  245.         /*** Color match all of the values ***/
  246.         
  247.         MatchColorSetValues(nColors, theSetColors, setSpace, theProfile, spaceToUse, profileToUse);
  248.                 
  249.         
  250.         /**** Create a PostScript array for each component ****/
  251.         
  252.         status = OutputComponentArrays(pRDParams, nColors, theSetColors, nComponents, level2Color, spaceToUse);
  253.         nrequire(status, failed_components);
  254.                 
  255.         /** If necessary put a color space on the stack, else put nil **/
  256.         
  257.         if (level2Color && !useDeviceSpace) {
  258.  
  259.             if (profileToUse == nil)
  260.                 profileToUse = (*hIEGlobals)->defaultProfileCopy;
  261.                 
  262.             status = ColorSpacePrimitive(hIEGlobals, spaceToUse, profileToUse, false, nil);
  263.             nrequire(status, failed_Output);        
  264.         
  265.         } else {
  266.         
  267.             status = DoNull(pRDParams);
  268.             nrequire(status, failed_Output);
  269.         
  270.         }//end if
  271.         
  272.         
  273.         /** Now create a PostScript indexed color space with the arrays on the operand stack **/
  274.         
  275.         pRDParams->resIndex = kMakeColorSet;
  276.         status = RDResPrintf(pRDParams, nComponents);
  277.         ncheck(status);
  278.  
  279. failed_components:
  280. failed_Output:
  281. failed_InvalidShapeSpace:
  282. failed_GetColors:
  283.         
  284.         /** Release the workspace, we're done with it **/
  285.         {
  286.             register OSErr saveStatus = PSReleaseWorkSpace(hIEGlobals);
  287.             ncheck(saveStatus);
  288.             if (status == noErr)
  289.                 status = saveStatus;
  290.                 
  291.         }
  292.  
  293. failed_GetWrkSpace:
  294. failed_ColorSpace:
  295.  
  296.         return(status);
  297.  
  298.     }//ColorSetPrimitive
  299.  
  300.  
  301.  
  302.  
  303.  
  304. //<FF>
  305. /*** Macro converts the long at srcePtr to 12 bit A, B, C (in low 12 bits), increments pointer ***/
  306.  
  307. #define GetNext12BitComponents(srcePtr, A, B, C) {                                        \
  308.                                                                                                                                             \
  309.             /* Get the 10 bit components of first of two source pixels*/        \
  310.                                                                                                                                             \
  311.             C = *srcePtr++;                                                                                                    \
  312.             B = (C >> 10) & 0x000003FF;                                                                            \
  313.             A = (C >> 20) & 0x000003FF;                                                                            \
  314.             C &= 0x000003FF;                                                                                                \
  315.                                                                                                                                             \
  316.             /** Convert them to 12 bits per component by replicating high two bits **/            \
  317.                                                                                                                                             \
  318.             A = (A << 2) | ((A >> 8) & 0x00000003);                                                    \
  319.             B = (B << 2) | ((B >> 8) & 0x00000003);                                                    \
  320.             C = (C << 2) | ((C >> 8) & 0x00000003);                                                    \
  321.         }
  322.  
  323.  
  324.  
  325. /****************************************************
  326.  
  327.     Convert32to36:
  328.     
  329.     Function converts a 32 bit per pixel (10 bits per component) raster
  330.     to a 12 bit per component (36 bits per pixel) raster.
  331.     
  332.         srceRaster:                    pointer to the source raster to convert.
  333.         destRaster:                    pointer to a 36 bit per pixel raster to write into.
  334.         width:                            width of the raster.
  335.  
  336.  
  337.     Conversion will be as follows:
  338.         3 sets of two pixels at a time.
  339.         That is 20 bits of source becomes 24 bits of destination.
  340.             
  341.             1 interation:
  342.                 A,B   ---> bytes 0 to 2
  343.                 C,A        ---> bytes 3 to 5
  344.                 B,C        ---> bytes 6 to 8
  345.     
  346. ******************************************************/
  347. void Convert32to36(unsigned long *srceRaster, Ptr destRaster, long width);
  348. void Convert32to36(unsigned long *srceRaster, Ptr destRaster, long width)
  349.     {
  350.         unsigned long            *srcePtr;
  351.         unsigned char            *dstPtr;
  352.         long                            iterations;
  353.         long                            i;
  354.         register unsigned long A, B, C;
  355.         
  356.         
  357.         srcePtr = srceRaster;
  358.         dstPtr = (unsigned char*)destRaster;
  359.         
  360.         iterations = width / 2;
  361.         
  362.         for (i = 0; i < iterations; ++i) {
  363.         
  364.             GetNext12BitComponents(srcePtr, A, B, C);
  365.             
  366.             /* Byte 0 of destination is high 8 bits of A */
  367.             *dstPtr++ = (A >> 4);
  368.             
  369.             /* Byte 1 of destination is low 4 bits of A plus high 4 bits of B */
  370.             *dstPtr++ = ((A & 0x0000000F) << 4) | (B >> 8);
  371.             
  372.             /* Byte 2 of destination is low 8 bits of B */
  373.             *dstPtr++ = (B & 0x000000FF);
  374.             
  375.             /* Byte 3 of destination is high 8 bits of C */
  376.             *dstPtr++ = (C >> 4);
  377.             
  378.             /* Fill high 4 bits of byte 4 of destination with low 4 bits of C, don't increment dest yet. */
  379.             *dstPtr = (C & 0x0000000F) << 4;
  380.  
  381.             
  382.             /** Get second pixel in iteration pair **/
  383.             
  384.             GetNext12BitComponents(srcePtr, A, B, C);
  385.  
  386.             /*  Fill low 4 bits of byte 4 of destination with high 4 bits of A */
  387.             *dstPtr++ |= (A >> 8);
  388.             
  389.             /* Byte 5 of destination is low 8 bits of A */
  390.             *dstPtr++ = (A & 0x000000FF);
  391.             
  392.             /* Byte 6 of destination is high 8 bits of B */
  393.             *dstPtr++ = (B >> 4);
  394.             
  395.             /* Byte 7 of destination is low 4 bits of B  plus high 4 bits of C */
  396.             *dstPtr++ = ((B & 0x0000000F) << 4) | (C >> 8);
  397.             
  398.             /* Byte 8 of destination is low 8 bits of C */
  399.             *dstPtr++ = (C & 0x000000FF);
  400.  
  401.         }//end for
  402.         
  403.         /** Handle the last odd pixel, same code as first half of above loop **/
  404.         
  405.         if (2 * iterations < width) {
  406.         
  407.             GetNext12BitComponents(srcePtr, A, B, C);
  408.             
  409.             /* Byte 0 of destination is high 8 bits of A */
  410.             *dstPtr++ = (A >> 4);
  411.             
  412.             /* Byte 1 of destination is low 4 bits of A plus high 4 bits of B */
  413.             *dstPtr++ = ((A & 0x0000000F) << 4) | (B >> 8);
  414.             
  415.             /* Byte 2 of destination is low 8 bits of B */
  416.             *dstPtr++ = (B & 0x000000FF);
  417.             
  418.             /* Byte 3 of destination is high 8 bits ox C */
  419.             *dstPtr++ = (C >> 4);
  420.             
  421.             /* Fill high 4 bits of byte 4 of destination with low 4 bits of C */
  422.             *dstPtr = (C & 0x0000000F) << 4;
  423.  
  424.         }//end if
  425.     
  426.  
  427.     }//Convert32to36
  428.  
  429.  
  430.  
  431. //<FF>
  432. /****************************************************
  433.  
  434.     OutputABC12Data:
  435.     
  436.     Routine takes the 30 bits of XYZ/LAB/LUV from each 32 bit xyz32, lab32, luv32,
  437.     converts them to 36 bits (12 per component) and buffers them.
  438.     
  439.     theBitmap:            Pointer to the bitmap record.
  440.     bandHeight:            number of rasters.
  441.     psRowBytes:            what PostScript thinks the rowbytes should be.
  442.     
  443. ******************************************************/
  444. OSErr OutputABC12Data(TIEGlobalsHdl hIEGlobals, gxBitmap* theBitmap, long bandHeight, long psRowBytes);
  445. OSErr OutputABC12Data(TIEGlobalsHdl hIEGlobals, gxBitmap* theBitmap, long bandHeight, long psRowBytes)
  446.     {
  447.         register long     i;
  448.         OSErr                         status;
  449.         Ptr                            p36;                            // Pointer to our 36 bit buffer.
  450.         Ptr                            pRaster;                    // Pointer to next offscreen raster.
  451.         long                        flags;
  452.         
  453.         flags = gxNoBufferOptions;
  454.         if ((*hIEGlobals)->params.renderOptions & gxNeedsHexOption)
  455.             flags = gxMakeBufferHex;
  456.             
  457.             
  458.         /*****
  459.             The buffer for the 24 bit data is at the end of the workspace allocated for the
  460.                     offscreen bitmap
  461.         *****/
  462.         p36 = theBitmap->image + theBitmap->height * theBitmap->rowBytes;
  463.         
  464.         pRaster = theBitmap->image;
  465.         for (i = bandHeight - 1; i >= 0; --i) {
  466.                         
  467.             Convert32to36((unsigned long*)pRaster, p36, theBitmap->width);
  468.             
  469.             status = (*hIEGlobals)->psDevice->BufferData(p36, psRowBytes, flags);
  470.             nrequire(status, failed_Raster);
  471.             
  472.             pRaster += theBitmap->rowBytes;
  473.         
  474.         }//end for
  475.         
  476. failed_Raster:
  477.  
  478.         return(status);
  479.     
  480.     }//OutputABC12Data
  481.  
  482.  
  483.  
  484. //<FF>
  485. /****************************************************
  486.  
  487.     OutputRGB32Data:
  488.     
  489.     Routine takes the 24 bits of RGB from each 32 bit rgb32Color
  490.     and buffers them.
  491.     
  492.     theBitmap:            Pointer to the bitmap record.
  493.     bandHeight:            number of rasters.
  494.     psRowBytes:            what PostScript thinks the rowbytes should be.
  495.     
  496. ******************************************************/
  497. OSErr OutputRGB32Data(TIEGlobalsHdl hIEGlobals, gxBitmap* theBitmap, long bandHeight, long psRowBytes);
  498. OSErr OutputRGB32Data(TIEGlobalsHdl hIEGlobals, gxBitmap* theBitmap, long bandHeight, long psRowBytes)
  499.     {
  500.         register long     i, j;
  501.         OSErr                         status;
  502.         Ptr                            p24;                            // Pointer to our 24 bit buffer.
  503.         Ptr                            pRaster;                    // Pointer to next offscreen raster.
  504.         Ptr                            pSrce, pDest;
  505.         long                        flags;
  506.         
  507.         flags = gxNoBufferOptions;
  508.         if ((*hIEGlobals)->params.renderOptions & gxNeedsHexOption)
  509.             flags = gxMakeBufferHex;
  510.             
  511.             
  512.         /*****
  513.             The buffer for the 24 bit data is at the end of the workspace allocated for the
  514.                     offscreen bitmap
  515.         *****/
  516.         p24 = theBitmap->image + theBitmap->height * theBitmap->rowBytes;
  517.         
  518.         pRaster = theBitmap->image;
  519.         for (i = bandHeight - 1; i >= 0; --i) {
  520.             
  521.             pSrce = pRaster;
  522.             pDest = p24;
  523.             
  524.             for (j = theBitmap->width - 1; j >= 0; --j) {
  525.  
  526.                 ++pSrce;                                    // Skip the unused byte.
  527.                 *pDest++ = *pSrce++;            //get red
  528.                 *pDest++ = *pSrce++;            //get blue
  529.                 *pDest++ = *pSrce++;            //get green
  530.                 
  531.             }//end for
  532.             
  533.             status = (*hIEGlobals)->psDevice->BufferData(p24, psRowBytes, flags);
  534.             nrequire(status, failed_Raster);
  535.             
  536.             pRaster += theBitmap->rowBytes;
  537.         
  538.         }//end for
  539.         
  540. failed_Raster:
  541.  
  542.         return(status);
  543.     
  544.     }//OutputRGB32Data
  545.  
  546.  
  547.  
  548. //<FF>
  549. /****************************************************
  550.  
  551.     OutputDirectData:
  552.     
  553.     Routine buffers data from a bitmap.
  554.     This will not work for rgb, however.  Because we must output
  555.     the triplets without the 4th byte.
  556.     
  557.         theBitmap:            pointer to the bitmap record.
  558.         bandHeight:            Number of rasters to output.
  559.         psRowBytes:            what PostScript thinks the rowbytes should be.
  560.     
  561. *****************************************************/
  562. OSErr OutputDirectData(TIEGlobalsHdl hIEGlobals, gxBitmap* theBitmap, long bandHeight, long psRowBytes);
  563. OSErr OutputDirectData(TIEGlobalsHdl hIEGlobals, gxBitmap* theBitmap, long bandHeight, long psRowBytes)
  564.     {
  565.         register short     i;
  566.         OSErr                         status;
  567.         register Ptr        pRaster;
  568.         long                        flags;
  569.         
  570.         flags = gxNoBufferOptions;
  571.         if ((*hIEGlobals)->params.renderOptions & gxNeedsHexOption)
  572.             flags = gxMakeBufferHex;
  573.         
  574.         pRaster = theBitmap->image;
  575.         for (i = bandHeight - 1; i >= 0; --i) {
  576.         
  577.             status = (*hIEGlobals)->psDevice->BufferData(pRaster, psRowBytes, flags);
  578.             nrequire(status, failed_Raster);
  579.             
  580.             #if DEBUGLEVEL > 0
  581.                 if (flags == gxMakeBufferHex) {
  582.                 
  583.                     char        carriageReturn[] = "\n\r";
  584.                     status = (*hIEGlobals)->psDevice->BufferData(carriageReturn, 2, gxNoBufferOptions);
  585.                     nrequire(status, failed_Raster);
  586.                 
  587.                 }//end if
  588.             #endif
  589.             
  590.             pRaster += theBitmap->rowBytes;
  591.         
  592.         }//end for
  593.         
  594. failed_Raster:
  595.  
  596.         return(status);
  597.     
  598.     }//OutputDirectData
  599.  
  600.  
  601. //<FF>
  602. /***************************************************
  603.  
  604.         BandBitmap:
  605.         
  606.         Routine bands the source bitmap shape Into
  607.         a bitmap in the image color space specified by
  608.         the client.
  609.         
  610.         theShape:                    The source bitmap shape.
  611.         offScreenBits:        a bitmap record with space, profile, pixelSize and set initialized.
  612.         psRowBytes:                #bytes per raster that PostScript is expecting.
  613.                 
  614. *****************************************************/
  615. #define kBandSize 50
  616. OSErr BandBitmap(TIEGlobalsHdl hIEGlobals, gxShape theShape, gxBitmap *offScreenBits, long psRowBytes);
  617. OSErr BandBitmap(TIEGlobalsHdl hIEGlobals, gxShape theShape, gxBitmap *offScreenBits, long psRowBytes)
  618.     {
  619.         OSErr                            status;
  620.         offscreen                    theBand;                                                // Offscreen for banding into.
  621.         gxTransform                oldTransform, tempTransform;
  622.         gxInk                            oldInk, tempInk;
  623.         gxShape                        offScreenBitShape;                            // Shape for offscreen bitmap.
  624.         gxBitmap                    srceBits;                                                // Bitmap record of the source shape.
  625.         long                            theSize;    
  626.         long                            bandY, bandHeight;
  627.         gxPoint                        srceLocation, zeroZero;
  628.         long                            rowLongs, rowBytes;
  629.         gxShapeAttribute    oldAttributes;
  630.         gxShape                        specialShape = nil;                            // If the bitmap is a "special" bitmap from the transfer mode machine.
  631.         gxShape                        eraser = nil;                                        // We must erase the offscreen in white each time when doing "special" bitmap.
  632.                         
  633.         zeroZero.x = 0; zeroZero.y = 0;
  634.  
  635.         oldAttributes = GXGetShapeAttributes(theShape);
  636.         GXSetShapeAttributes(theShape, oldAttributes & ~gxMapTransformShape);  // so MoveShapeTo moves position, not transform
  637.         
  638.         GXGetBitmap(theShape, &srceBits, &srceLocation);    // Get the bitmap record of the shape.
  639.         
  640.         /**
  641.             See if the bitmap is "special" bitmap generated by the RenderTransferMode machine.
  642.         **/
  643.         if (srceBits.rowBytes == -sizeof(gxShape)) {            // rowbytes -4 signals "special bitmap"
  644.             gxColor whiteColor;
  645.             specialShape = (gxShape)(srceBits.image);        
  646.             eraser = GXNewShape(gxFullType);
  647.             whiteColor.profile = srceBits.profile;
  648.             whiteColor.space = gxGraySpace;
  649.             whiteColor.element.gray = 0xFFFF;
  650.             GXSetShapeColor(eraser, &whiteColor);
  651.         }//end if
  652.         
  653.                 
  654.         /** Set up the offscreen bitmap **/
  655.         
  656.         offScreenBits->width = srceBits.width;
  657.         offScreenBits->height = srceBits.height > kBandSize ? kBandSize : srceBits.height;    //MIN( srceBits.height, kBandSize );
  658.         
  659.         rowBytes =  (offScreenBits->width * offScreenBits->pixelSize) / 8;
  660.         rowLongs = rowBytes / 4;
  661.         if ((4 * rowLongs) < rowBytes);
  662.             ++rowLongs;
  663.             
  664.         offScreenBits->rowBytes = 4 * rowLongs;
  665.         
  666.         
  667.         /** Allocate space for the offscreen bitmap. **/
  668.         
  669.         theSize = offScreenBits->rowBytes * offScreenBits->height;
  670.         
  671.         /********
  672.             RGB32 and the XYZ spaces require an additional buffer to hold 24 or 36 bit triplets
  673.             because the raw data in the bitmap will be have an unused byte
  674.             at the beginning.  So OutputRGB32Data will use this extra buffer
  675.             to create the 24 bit data and OutputABC12Data will use it for the 36 bit data.
  676.         ********/
  677.         if ((offScreenBits->space == gxRGB32Space) || 
  678.                 (offScreenBits->space == gxXYZ32Space) || 
  679.                 (offScreenBits->space == gxLAB32Space) || 
  680.                 (offScreenBits->space == gxLUV32Space) )
  681.             theSize += psRowBytes;
  682.         
  683.         status = PSSetWorkSpaceSize(hIEGlobals, theSize);
  684.         nrequire(status, failed_GetSpace);
  685.         
  686.         HLockHi((*hIEGlobals)->hWorkSpace);
  687.         
  688.         /** Create the offscreen **/
  689.         
  690.         offScreenBits->image = *((*hIEGlobals)->hWorkSpace);
  691.                 
  692.         offScreenBitShape = GXNewBitmap(offScreenBits, &zeroZero);        // Same location as source so pixels line up.
  693.         status = GXGetGraphicsError(nil);
  694.         nrequire(status, failed_CreateBitmap);
  695.         
  696.         
  697.         /*****
  698.             Do a GetBitmap because NewBitmap may have updated some fields in the bitmap structure.
  699.                     such as colorSpace and colorSet
  700.         *****/
  701.         
  702.         GXGetBitmap(offScreenBitShape, offScreenBits, nil);
  703.                 
  704.         CreateOffscreen(&theBand, offScreenBitShape);
  705.         nrequire(status = GXGetGraphicsError(nil), failed_CreateOffscreen);
  706.         
  707.         /* Make sure matching is enabled for the port */
  708.         
  709.         GXSetViewPortAttributes(theBand.port, GXGetViewPortAttributes(theBand.port) | gxEnableMatchPort);
  710.  
  711.  
  712.         /*******************************
  713.         
  714.             Now band the bitmap
  715.             
  716.         ********************************/
  717.         /*******
  718.             Give the shape an identity trasnform (which we will move to accomplish banding):
  719.             we don't want it transformed while we band into offscreen.
  720.             The new transform's viewport will be the offscreen's viewport.
  721.                         
  722.         *******/
  723.         
  724.         oldTransform = GXCloneTransform(GXGetShapeTransform(theShape));
  725.         tempTransform = GXNewTransform();
  726.         GXSetTransformViewPorts(tempTransform, 1, &(theBand.port));
  727.         GXSetShapeTransform(theShape, tempTransform);
  728.         GXMoveShapeTo(theShape, 0, 0);                                                                    // Line it up with offscreen.
  729.  
  730.         /* If we are drawing the "special" bitmap from the transfer mode engine, then set up for device space */
  731.         if (specialShape != nil) {
  732.             gxMapping deviceMapping;
  733.             CopyToMapping(&deviceMapping, &(*hIEGlobals)->deviceMapping);
  734.             MoveMapping(&deviceMapping, -srceLocation.x, -srceLocation.y);
  735.             GXSetShapeViewPorts(specialShape, 1, &(theBand.port));
  736.             GXSetShapeViewPorts(eraser, 1, &(theBand.port));
  737.             GXSetViewPortMapping(theBand.port, &deviceMapping);
  738.         }//end if
  739.  
  740.         /****
  741.             Put a default ink on so it has copy transfer-mode.
  742.             This should mean we don't have to earase the destination first.
  743.         ****/
  744.         oldInk = GXCloneInk(GXGetShapeInk(theShape));
  745.         tempInk = GXNewInk();
  746.         GXSetShapeInk(theShape, tempInk);
  747.         
  748.         /**
  749.             Now loop to band out the image to the PostScript device.
  750.         **/
  751.         for (bandY = 0; bandY < srceBits.height; bandY += kBandSize) {
  752.  
  753.             bandHeight = kBandSize;
  754.             if (bandY + bandHeight >= srceBits.height)
  755.                 bandHeight = srceBits.height - bandY;
  756.  
  757.             if (specialShape == nil) {        
  758.                 GXDrawShape(theShape);
  759.                 GXMoveTransform(tempTransform, 0, -ff(kBandSize));        // move the shape for the next band.
  760.             } else {
  761.                 gxMapping            portMap;
  762.                 GXDrawShape(eraser);
  763.                 GXDrawShape(specialShape);
  764.                 /* Map the port, we do this here rather than moving the shape becuase of port alligned patterns, etc. */
  765.                 GXGetViewPortMapping(theBand.port, &portMap);
  766.                 MoveMapping(&portMap, 0, -ff(kBandSize));
  767.                 GXSetViewPortMapping(theBand.port, &portMap);
  768.             }//end if
  769.             status = GXGetGraphicsError(nil);
  770.             nrequire(status, failed_Draw);
  771.  
  772.             /** Use monet to match the bitmap if necessary **/                
  773.             
  774.             /** Output the data to PostScript **/
  775.             switch(offScreenBits->space) {
  776.  
  777.                 case gxIndexedSpace:
  778.                 case gxCMYK32Space:
  779.                     status = OutputDirectData(hIEGlobals, offScreenBits, bandHeight, psRowBytes);
  780.                     ncheck(status);
  781.                     break;
  782.                     
  783.                 case gxRGB32Space:
  784.                     status = OutputRGB32Data(hIEGlobals, offScreenBits, bandHeight, psRowBytes);
  785.                     ncheck(status);
  786.                     break;
  787.                     
  788.                 case gxXYZ32Space:
  789.                 case gxLAB32Space:
  790.                 case gxLUV32Space:
  791.                     status = OutputABC12Data(hIEGlobals, offScreenBits, bandHeight, psRowBytes);
  792.                     ncheck(status);
  793.                     break;
  794.                                 
  795.                 default:
  796.                     #if DEBUGLEVEL > 0
  797.                         dprintf(notrace, "Image Color Space not implemented: %d", (long)(offScreenBits->space));
  798.                     #endif
  799.                     break;
  800.             
  801.             }//end switch
  802.             
  803.             nrequire(status, failed_Output);
  804.  
  805.         }//end for
  806.  
  807.  
  808.         /** Output a carriage-return and new line just for file-clarity's sake after all bitmap data **/
  809.         
  810.         nrequire(status = (*hIEGlobals)->psDevice->BufferData("\r\n", 2, gxNoBufferOptions), failed_Output);
  811.  
  812. failed_Draw:
  813.  
  814.         
  815. failed_Output:
  816.  
  817.         GXSetShapeTransform(theShape, oldTransform);                                    // restore the bitmap's transform.
  818.         GXSetShapeInk(theShape, oldInk);                                                            // restore the bitmap's ink.
  819.         GXMoveShapeTo(theShape, srceLocation.x, srceLocation.y);            // Put it back where it was.
  820.         GXSetShapeAttributes(theShape, oldAttributes);                                // Restore the attributes
  821.         GXDisposeInk(tempInk);                                                                                // Clean up inks.    
  822.         GXDisposeInk(oldInk);
  823.         GXDisposeTransform(tempTransform);                                                        // Clean up transforms.
  824.         GXDisposeTransform(oldTransform);
  825.         DisposeOffscreen(&theBand);                                                                        // Clean up offscreen.
  826.         
  827. failed_CreateOffscreen:
  828.         
  829.         GXDisposeShape(offScreenBitShape);
  830.  
  831. failed_CreateBitmap:
  832.  
  833.         {
  834.             OSErr saveStatus = PSReleaseWorkSpace(hIEGlobals);
  835.             ncheck(saveStatus);
  836.             if (status == noErr)
  837.                 status = saveStatus;
  838.                 
  839.         }
  840.         
  841. failed_GetSpace:
  842.  
  843.         return(status);
  844.     
  845.     }//BandBitmap
  846.  
  847.  
  848.  
  849. //<FF>
  850. /*************************************
  851.     Routine: SetupOffscreenBitmap.
  852.     
  853.     Routine sets up the offscreen bitmap to be
  854.     used for banding the bitmap.  The bitmap record
  855.     returned will be used to set up an offscreen
  856.     for banding
  857.     
  858.     theBits:                pointer to the source bitmap record.
  859.     offscreenBits:    pointer a bitmap record for the offscreen
  860.     cmpSize:                bits/component to use for PostScript image operation.
  861.     cmpCount:                # of components.
  862.     useLevel2:            (Input/Output)  (Input true means try to, output false means can't)    
  863.     
  864. ****************************************/    
  865. void    SetupOffscreenBitmap(TIEGlobalsHdl hIEGlobals, gxBitmap *theBits, gxBitmap *offscreenBits, long *cmpSize, long *cmpCount, Boolean *useLevel2);
  866. void    SetupOffscreenBitmap(TIEGlobalsHdl hIEGlobals, gxBitmap *theBits, gxBitmap *offscreenBits, long *cmpSize, long *cmpCount, Boolean *useLevel2)
  867.     {
  868.         TIEGlobalsPtr             pGlobals = *hIEGlobals;
  869.         Boolean                            useIndexed = false;                        // should we use an indexed color space?
  870.     
  871.         if (theBits->space == gxIndexedSpace)        {
  872.         
  873.             /**    1, 2 or 4 bit indexed should always be used. **/
  874.             
  875.             if ( theBits->pixelSize < 8 )
  876.                 useIndexed = true;
  877.                 
  878.         
  879.             /****
  880.                 For 8-bit, it only makes sense to use colorset if the device is not graySpace,
  881.                         or we are using level-2 color.  The net result is that for 8 bit indexed,
  882.                         where the device is level-1 gray we just get an image operator.  (Because
  883.                         the offscreen we will use will be the gray color set offscreen which
  884.                         is equivelent to the standard PostScript image operator.
  885.             ****/
  886.         
  887.             if ( (theBits->pixelSize == 8) && ( (pGlobals->params.devCSpace != gxGraySpace) || *useLevel2 ) )
  888.                 useIndexed = true;
  889.         
  890.         }//end if
  891.  
  892.  
  893.         /** Set up the fields of the offscreen **/
  894.         
  895.         if (useIndexed)    {
  896.         
  897.             offscreenBits->set = theBits->set;
  898.             offscreenBits->space = theBits->space;
  899.             offscreenBits->profile = theBits->profile;
  900.             offscreenBits->pixelSize = theBits->pixelSize;
  901.             *cmpCount = 1;
  902.             *cmpSize = theBits->pixelSize;
  903.         
  904.         } else {
  905.  
  906.             /*****
  907.                 For level-2 color option set up the offscreen to convert to a level-2 
  908.                     supported space and profile.
  909.                 otherwise set up the offscreen to reflect the device's color space
  910.             ******/
  911.             
  912.             if (*useLevel2) {
  913.             
  914.                 long        profileSize;
  915.                 Boolean    useDeviceSpace = false;                // Should we use postscript device color spaces ?
  916.                 /******
  917.                     If the profile is nil (though this should never be the case from an unflattened shape
  918.                     Make it the default profile copy so we can pass it through clone and dispose
  919.                     without headaches
  920.                 *******/
  921.                 if (theBits->profile == nil)
  922.                     theBits->profile = (*hIEGlobals)->defaultProfileCopy;
  923.                 
  924.                 /* Find out if we should do matching */
  925.                 profileSize = GetColorProfileSize(theBits->profile, nil);
  926.                 if (profileSize == 0)
  927.                     useDeviceSpace = true;
  928.                                     
  929.                 offscreenBits->profile = theBits->profile;
  930.                 offscreenBits->pixelSize = 32;
  931.                 *cmpCount = 3;
  932.                 
  933.                 switch(theBits->space) {
  934.                 
  935.                     case gxCMYK32Space:
  936.                         if (useDeviceSpace) {
  937.                             offscreenBits->space = gxCMYK32Space;
  938.                             *cmpSize = 8;
  939.                             *cmpCount = 4;
  940.                             *useLevel2 = false;                // Make BitmapPrimitive do normal colorimage.
  941.                         } else {
  942.                             /***
  943.                                 For color Level2 matching, convert cmyk to xyz - there is no way to do cmyk 
  944.                                 in 3 component PostScript device independant spaces.
  945.                             ****/
  946.                             offscreenBits->space = gxXYZ32Space;
  947.                             *cmpSize = 12;
  948.                             *cmpCount = 3;
  949.                         }//end if
  950.                         break;
  951.  
  952.                     case gxYXY32Space:
  953.                     case gxLUV32Space:                        // maybe able to support without conversion to XYZ
  954.                     case gxLAB32Space:                        // maybe able to support without conversion to XYZ
  955.                     case gxYIQ32Space:                        // maybe able to support without conversion to XYZ
  956.                     case gxXYZ32Space:
  957.                         offscreenBits->space = gxXYZ32Space;
  958.                         *cmpSize = 12;
  959.                         break;
  960.                         
  961.                     case gxRGB16Space:
  962.                     case gxHSV32Space:
  963.                     case gxHLS32Space:
  964.                     case gxARGB32Space:
  965.                     case gxRGB32Space:
  966.                         offscreenBits->space = gxRGB32Space;
  967.                         *cmpSize = 8;
  968.                         *useLevel2 = !useDeviceSpace;            // Make BitmapPrimitive do normal colorimage for no-match profile.
  969.                         break;
  970.                         
  971.                     default:
  972.                         #if DEBUGLEVEL > 0
  973.                         dprintf(notrace, "Bug, Colorspace not implemented: %d", theBits->space);
  974.                         #endif
  975.                         break;
  976.                 
  977.                 }//end switch
  978.                 
  979.             }    else {
  980.             
  981.                 /** Set up the offscreen for a standard level-1 image or colorimage operator **/
  982.                 
  983.                 offscreenBits->profile = pGlobals->params.devCProfile;
  984.                 switch(pGlobals->params.devCSpace) {
  985.                 
  986.                     case gxCMYKSpace:
  987.                         offscreenBits->pixelSize = 32;
  988.                         offscreenBits->space = gxCMYK32Space;
  989.                         *cmpSize = 8;
  990.                         *cmpCount = 4;
  991.                         break;
  992.                         
  993.                     case gxRGBSpace:
  994.                         offscreenBits->pixelSize = 32;
  995.                         offscreenBits->space = gxRGB32Space;
  996.                         *cmpSize = 8;
  997.                         *cmpCount = 3;
  998.                         break;
  999.                         
  1000.                     case gxGraySpace:
  1001.                         offscreenBits->pixelSize = 8;
  1002.                         offscreenBits->space = gxIndexedSpace;
  1003.                         offscreenBits->set = pGlobals->graySet;
  1004.                         *cmpSize = 8;
  1005.                         *cmpCount = 1;
  1006.                         break;
  1007.                         
  1008.                     default:
  1009.                         #if DEBUGLEVEL > 0
  1010.                         dprintf(notrace, "Bug, Unsupported device color space: %d", pGlobals->params.devCSpace);
  1011.                         #endif
  1012.                         break;
  1013.                         
  1014.                 }//end switch
  1015.                 
  1016.             }//end if
  1017.         
  1018.         }//end if
  1019.     
  1020.     }//SetupOffscreenBitmap
  1021.  
  1022.  
  1023.  
  1024. //<FF>
  1025. /***********************************************
  1026.  
  1027.         BitmapPrimitive:
  1028.         
  1029.         Routine controls the translation of all bitmap shapes
  1030.         into PostScript.
  1031.         
  1032.         Sets up the parts of the offscreen bitmap structure for rendering into:
  1033.                 pixelSize, colorSpace, colorProfile, and colorSet.  The rest will
  1034.                 be set up by BandBitmap        
  1035.         
  1036. *************************************************/
  1037. OSErr BitmapPrimitive(TIEGlobalsHdl hIEGlobals, gxShape theShape, TgeometryOptions geomOptions)
  1038.     {
  1039.         OSErr                        status;
  1040.         gxBitmap                theBits;                                    //    the bitmap structure from the shape.
  1041.         gxBitmap                offScreenBits;                        //    Offscreen bitmap to render into.
  1042.         gxPoint                    location;                                    //    bitmaps location.
  1043.         long                        cmpSize;                                    //     color component size for PostScript
  1044.         long                        cmpCount;                                    //     Number of color components for PostScript.
  1045.         long                        psRowBytes;                                //    Number of bytes per raster for PostScript.
  1046.         TIEGlobalsPtr        pGlobals;    
  1047.         TRDParams*            pRDParams;
  1048.         Boolean                    doImageMask = false;            // Can the bitmap be imagemasked?
  1049.         Boolean                    doIndexedColors = false;    // Are we using an indexed color space?
  1050.         Boolean                    needsEOD = false;                    // Do we need to output an EOD character for L2 file filter?
  1051.         Boolean                    useLevel2 = false;                // Are we using level-2 color?
  1052.         long                        needsHex;                                    // true or false for outputting bitmap data as hex.
  1053.  
  1054.  
  1055.         pGlobals = *hIEGlobals;
  1056.         pRDParams = pGlobals->pRDParams;
  1057.  
  1058.         needsHex = pGlobals->params.renderOptions & gxNeedsHexOption ? true : false;
  1059.         useLevel2 = pGlobals->params.renderOptions & gxUseLevel2ColorOption ? true : false;
  1060.         
  1061.         GXGetBitmap(theShape, &theBits, &location);                                // Get the bitmap data structure.
  1062.         status = GXGetGraphicsError(nil);
  1063.         nrequire(status, failed_GetBitmap);
  1064.  
  1065.         /** Check to see if the bitmap has dimensions worth processing **/
  1066.         if (theBits.width > 0 && theBits.height > 0)    {
  1067.         
  1068.             /** Figure out what the bits PS will need **/
  1069.             SetupOffscreenBitmap(hIEGlobals, &theBits, &offScreenBits, &cmpSize, &cmpCount, &useLevel2);
  1070.                         
  1071.             /** Determine what postscript will be used based on the offscreen that was set up **/
  1072.             
  1073.             doIndexedColors = false;
  1074.             doImageMask = false;
  1075.             if (offScreenBits.space == gxIndexedSpace) {
  1076.             
  1077.                 if (offScreenBits.set != pGlobals->graySet) {            // graySet means use gray image operator.
  1078.                 
  1079.                     doIndexedColors = true;                                                    // any other set means use indexed.
  1080.                     if (offScreenBits.pixelSize == 1)
  1081.                         doImageMask = true;
  1082.                     
  1083.                 }//end if
  1084.                 
  1085.             }//end if
  1086.                     
  1087.             /** Calculate the number of bytes per raster that PostScript will expect **/
  1088.             
  1089.             psRowBytes = (theBits.width * cmpCount * cmpSize + 7) / 8;
  1090.     
  1091.             if (geomOptions & eMakeProcedure) {
  1092.             
  1093.                 /************************************************
  1094.                     The PostScript for a procedure will be:
  1095.                         colorSet dictionary     (for indexed)
  1096.                         or a colorSpace array (level-2 direct color only) 
  1097.                         bitmapStrings 
  1098.                         bits/pixel
  1099.                         geometry procedure
  1100.                 *************************************************/
  1101.             
  1102.             
  1103.                 /****
  1104.                     Output the colorset dictionary
  1105.                 ****/
  1106.                 if (doIndexedColors) {
  1107.                 
  1108.                     status = ColorSetPrimitive(hIEGlobals, theBits.set, theBits.profile);
  1109.                     nrequire(status, failed_DoBitmap);
  1110.                     
  1111.                 } else if (useLevel2) {
  1112.                 
  1113.                     status = ColorSpacePrimitive(hIEGlobals, offScreenBits.space, offScreenBits.profile, false, nil);
  1114.                     nrequire(status, failed_DoBitmap);
  1115.                 
  1116.                 } else {
  1117.                 
  1118.                     status = DoNull(pRDParams);
  1119.                     nrequire(status, failed_DoBitmap);
  1120.                     
  1121.                 }//end if
  1122.                                 
  1123.                 /****
  1124.                     Make the bitmap strings
  1125.                 ****/
  1126.                 
  1127.                 /* output the header for making the strings */
  1128.                 pRDParams->resIndex = kMakeBitStrings;
  1129.                 status = RDResPrintf(pRDParams, needsHex, psRowBytes * theBits.height);    
  1130.                 nrequire(status, failed_DoBitmap);
  1131.                 
  1132.                 /*****
  1133.                     Flush the RDResPrintf buffer and
  1134.                     Output the image data
  1135.                 *****/
  1136.                 status = RDFlushBuffer((*hIEGlobals)->rdMap);
  1137.                 nrequire(status, failed_rdFlush);
  1138.  
  1139.                 /* Band the data to make the strings */
  1140.                 status = BandBitmap(hIEGlobals, theShape, &offScreenBits, psRowBytes);
  1141.                 nrequire(status, failed_DoBitmap);
  1142.                 
  1143.                 /****
  1144.                     First put the bits per pixel on the stack for MakeShapeDict:
  1145.                 ****/
  1146.     
  1147.                 pRDParams->resIndex = kDoInt;
  1148.                 nrequire(status = RDResPrintf(pRDParams, cmpSize), failed_DoBitmap);
  1149.             
  1150.                 /****
  1151.                     Make the geometry procedure
  1152.                 ****/
  1153.     
  1154.                 if (doImageMask) {
  1155.                 
  1156.                     pRDParams->resIndex = k1bitBitmapProc;
  1157.                     status = RDResPrintf(pRDParams, theBits.width, theBits.height, &location);
  1158.                 
  1159.                 } else if (doIndexedColors) {
  1160.                 
  1161.                     pRDParams->resIndex = kIndexedBitProc;
  1162.                     status = RDResPrintf(pRDParams, theBits.width, theBits.height, cmpSize, &location);
  1163.                 
  1164.                 } else if (useLevel2) {
  1165.                 
  1166.                     pRDParams->resIndex = kL2BitmapProc;
  1167.                     status = RDResPrintf(pRDParams, theBits.width, theBits.height, cmpSize, &location);
  1168.                 
  1169.                 } else {
  1170.                 
  1171.                     pRDParams->resIndex = kBitmapProc;
  1172.                     status = RDResPrintf(pRDParams, cmpCount, theBits.width, theBits.height, cmpSize, &location);
  1173.                     
  1174.                 }//end if
  1175.                 nrequire(status, failed_DoBitmap);
  1176.             
  1177.             
  1178.             } else {
  1179.             
  1180.                 /*************************************************
  1181.                     The PostScript for drawing will be:
  1182.                         setting the colorSet if necessary
  1183.                         setting the colorspace if necessary (for level-2 color options)
  1184.                         image header (parameters for DoBitmap or DoIndexedBitmap
  1185.                         the data
  1186.                 *************************************************/
  1187.             
  1188.                 /****
  1189.                     Set the colorSet if necessary
  1190.                 ****/
  1191.                 if (doIndexedColors && 
  1192.                         ((pGlobals->ieStateFlags & eColorSetOutOfDate) || 
  1193.                         !PSEqualColorSet(pGlobals->theColorSet, theBits.set)) ) {
  1194.     
  1195.                     status = ColorSetPrimitive(hIEGlobals, theBits.set, theBits.profile);
  1196.                     nrequire(status, failed_DoBitmap);
  1197.     
  1198.                     pGlobals = *hIEGlobals;                                                    // ColorSetPrim could have moved memory.
  1199.                     PSDisposeColorSet(pGlobals->theColorSet);
  1200.                     pGlobals->theColorSet = GXCloneColorSet(theBits.set);
  1201.                     pRDParams->resIndex = kSetColorSet;
  1202.                     status = RDResPrintf(pRDParams);
  1203.                     nrequire(status, failed_DoBitmap);
  1204.                     
  1205.                     pGlobals = *hIEGlobals;                                                            // resprintf could have moved memory.
  1206.                     pGlobals->ieStateFlags &= ~eColorSetOutOfDate;            // it is now current.
  1207.                 
  1208.                 }//end if
  1209.                             
  1210.                 /****
  1211.                     Do the image header
  1212.                 *****/
  1213.                 if (doImageMask) {
  1214.                 
  1215.                     if (GXGetShapeTags(theShape, rasterizedShapeTag, 1, gxSelectToEnd, nil) ) {                /** Is this some rasterized text with an additional matrix?? **/
  1216.  
  1217.                         /** Bitmaps that are rasterizations of other shapes (kanji text) have additional mappings on them. **/
  1218.                         
  1219.                         gxMapping                    *additionalMapping;
  1220.                         gxTag                            psrsTag;
  1221.                         
  1222.                         GXGetShapeTags(theShape, rasterizedShapeTag, 1, gxSelectToEnd, &psrsTag);
  1223.                         GXLockTag(psrsTag);
  1224.                         additionalMapping = (gxMapping*)GXGetTagStructure(psrsTag, nil);
  1225.                         
  1226.                         pRDParams->resIndex = k1bitBitmapPSRS;
  1227.                         status = RDResPrintf(pRDParams, theBits.width, theBits.height, &location, needsHex, psRowBytes, 
  1228.                                                                     additionalMapping->map[0][0], additionalMapping->map[0][1],
  1229.                                                                     additionalMapping->map[1][0], additionalMapping->map[1][1],
  1230.                                                                     additionalMapping->map[2][0], additionalMapping->map[2][1],
  1231.                                                                     additionalMapping->map[2][2]);
  1232.  
  1233.                         GXUnlockTag(psrsTag);
  1234.                         
  1235.                     } else {        /** Thank god!  Just a normal bitmap **/
  1236.                     
  1237.                         pRDParams->resIndex = k1bitBitmap;
  1238.                         status = RDResPrintf(pRDParams, theBits.width, theBits.height, &location, 
  1239.                                                                     needsHex, psRowBytes);
  1240.                                                                     
  1241.                     }//end if
  1242.                 
  1243.                 } else if (doIndexedColors) {
  1244.                 
  1245.                     pRDParams->resIndex = kIndexedImage;
  1246.                     status = RDResPrintf(pRDParams, theBits.width, theBits.height, cmpSize, &location,
  1247.                                                                 needsHex, psRowBytes);
  1248.                 
  1249.                 } else if (useLevel2) {
  1250.     
  1251.                     /****
  1252.                         Set the color space
  1253.                     ****/
  1254.                     
  1255.                     status = ColorSpacePrimitive(hIEGlobals, offScreenBits.space, offScreenBits.profile, true, nil);
  1256.                     nrequire(status, failed_DoBitmap);
  1257.                     
  1258.                     pRDParams->resIndex = kL2Image;
  1259.                     status = RDResPrintf(pRDParams, theBits.width, theBits.height, cmpSize, &location, needsHex);
  1260.     
  1261.                     /** Level 2 image uses dictionary which will use filter for hex, so we need EOD **/
  1262.                     if (needsHex)
  1263.                         needsEOD = true;
  1264.     
  1265.                 } else {
  1266.                 
  1267.                     pRDParams->resIndex = kImage;
  1268.                     status = RDResPrintf(pRDParams, cmpCount, theBits.width, theBits.height, 
  1269.                                                                     cmpSize, &location, needsHex, psRowBytes);
  1270.                     
  1271.                     /* If we did a normal bitmap then that means if we are level-2 we are now in L2 device space */
  1272.                     pGlobals = *hIEGlobals;
  1273.                     pGlobals->gStateNest[pGlobals->gStateDepth].level2DevSpace = true;     /* Now in Level-2 device space */
  1274.                     pGlobals->gStateNest[pGlobals->gStateDepth].currSpace = theBits.space;
  1275.                     
  1276.                 }//end if
  1277.                 nrequire(status, failed_DoBitmap);
  1278.         
  1279.                 /*****
  1280.                     Flush the RDResPrintf buffer and
  1281.                     Output the image data
  1282.                 *****/
  1283.                 status = RDFlushBuffer((*hIEGlobals)->rdMap);
  1284.                 nrequire(status, failed_rdFlush);
  1285.                 
  1286.                 status = BandBitmap(hIEGlobals, theShape, &offScreenBits, psRowBytes);
  1287.                 nrequire(status, failed_DoBitmap);
  1288.     
  1289.                 if (needsEOD) {
  1290.                     
  1291.                     /** The EOD for the hex filter is the ">" character **/
  1292.                     nrequire(status = (*hIEGlobals)->psDevice->BufferData(">\r\n", 3, gxNoBufferOptions), failed_OutputEOD);
  1293.                             
  1294.                 }//end if
  1295.                         
  1296.             
  1297.             }//end if
  1298.  
  1299.  
  1300.         }//end if
  1301.                     
  1302.         
  1303. failed_OutputEOD:    
  1304. failed_rdFlush:
  1305. failed_DoBitmap:
  1306.  
  1307. failed_GetColorSpace:
  1308.  
  1309. failed_GetBitmap:
  1310.  
  1311.         return(status);
  1312.     
  1313.     }//BitmapPrimitive
  1314.  
  1315.